package littlecyberwar.tool;

import javax.swing.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.util.*;

import littlecyberwar.ui.*;
import littlecyberwar.util.*;

// a common superclass for different kind of mouse action to game command
// i.e. move straight ahead
// rotate
// side step, etc.
public class MouseFreeFormHandler extends MouseStraightHandler {
	ArrayList deltaX;	// the center point delta between first element and the signature
	ArrayList deltaY;	// the center point delta between first element and the signature
	double sigCenterX;
	double sigCenterY;
	
  public MouseFreeFormHandler() {
    super();
    // startDragX = -1;
    // startDragY = -1;
    id = H_FREEFORM;
	unitSelectedText = "Drag mouse in any direction and release button to move unit.";
	noUnitSelectedText = "Click on a unit to select for freeform movement.";
	
	deltaX = new ArrayList();
	deltaY = new ArrayList();
  }

	public void startAction( MouseEvent e ) {
	  super.startAction(e);

		deltaX.clear();
		deltaY.clear();
		Element signatureElement =((SelectedElementContainer)selectedElements.get(0)).element;				
	  	sigCenterX = signatureElement.getFinalShape().getBounds2D().getCenterX();
	  	sigCenterY = signatureElement.getFinalShape().getBounds2D().getCenterY();
	  
	  	for (int i=0; i < selectedElements.size(); i++ ){
			SelectedElementContainer selEl = (SelectedElementContainer)selectedElements.get(i);
			Element el = selEl.element;

			// now get the difference of where the center is
			double sigDiffX = el.getFinalShape().getBounds2D().getCenterX()-sigCenterX;
			double sigDiffY = el.getFinalShape().getBounds2D().getCenterY()-sigCenterY;
	  		deltaX.add(i, new Double(sigDiffX));
			deltaY.add(i, new Double(sigDiffY));
			//Debug.out("deltaX.add(i, new Double(sigDiffX)): " + i + ", diffX=" + sigDiffX);
			//Debug.out("deltaY.add(i, new Double(sigDiffY)): " + i + ", diffY=" + sigDiffY);
	  	}	  
	}

	/**
	 * When this ends, the selectedArea contains the new union 
	 * of all the elements
	 */
  protected void dragSelected( Point newP ) {
    // attempt to use transform on point to see if we can change
    // coordinate to conform to that of the new user space,
    // then just translate from that
    //
//	selectedTrans = ((SelectedElementContainer)selectedElements.get(0)).element.getTransform();
//    try {
//      endDragP = selectedTrans.inverseTransform(newP, endDragP);
//    } catch ( Exception ex ) {
//      ex.printStackTrace();
//    }
//
//    //System.out.println("newP x=" + newP.getX() + ", y=" + newP.getY() );
//
//    // now figure out just the Y difference between the 2 points
//    double diffY = endDragP.getY() - startDragP.getY();
//    double diffX = endDragP.getX() - startDragP.getX();
    //System.out.println("transformed diffY= " + diffY );
    
    /** 
     * now loop through each element in the selected element arraylist
    * 	and apply the change to all of them
	 * This is the ongoing location of the element
	 * also need to rebuild selectedArea
	 */
	AffineTransform currTrans;
	Shape originalRec;
//	selectedArea = new Area();
	
//    for (int i=0; i < selectedElements.size(); i++ ){
//    	SelectedElementContainer selEl = (SelectedElementContainer)selectedElements.get(i);
//    	Element el = selEl.element;
//		AffineTransform trans= el.getTransform();
//		currTrans = (AffineTransform)trans.clone();
//		currTrans.translate(diffX, diffY);
//		originalRec = el.getRectangle();
//		selEl.selectedRectangle = currTrans.createTransformedShape(originalRec);
//		selEl.currTrans = currTrans;
//		
//		Area a = new Area(selEl.selectedRectangle.getBounds2D());
//		selectedArea.add(a);			
//    }

	// create a transform for the signature element
	double diffY=0;
	double diffX=0;
	Element signatureElement =((SelectedElementContainer)selectedElements.get(0)).element; 
	selectedTrans = signatureElement.getTransform();
	try {
		endDragP = selectedTrans.inverseTransform(newP, endDragP);
	} catch ( Exception ex ) {
		ex.printStackTrace();
	}

  	//System.out.println("newP x=" + newP.getX() + ", y=" + newP.getY() );

  	// now figure out just the Y difference between the 2 points
  	diffY = endDragP.getY() - startDragP.getY();
  	diffX = endDragP.getX() - startDragP.getX();	
	  	  
  	// now loop through all the other elements
	for (int i=0; i < selectedElements.size(); i++ ){
		// now we need to find out the difference between the signature element and the current element		
		SelectedElementContainer selEl = (SelectedElementContainer)selectedElements.get(i);
		Element el = selEl.element;
		AffineTransform trans= el.getTransform();

		// now transform back the adjusted startDragP and End dragP
		AffineTransform startPointTrans = AffineTransform.getTranslateInstance(((Double)deltaX.get(i)).doubleValue(), ((Double)deltaY.get(i)).doubleValue());
		Point2D currStartDragP=null, currEndDragP = null; 
		currStartDragP = startPointTrans.transform(dragSelectStartPoint, currStartDragP);		
		currEndDragP = startPointTrans.transform(newP, currEndDragP);
		
		Point2D currInvStart = null;
		Point2D cirrInvEnd = null;
		
		// now inverse transform back into the origin
		try {
			currInvStart = trans.inverseTransform(currStartDragP, currInvStart);
			cirrInvEnd = trans.inverseTransform(currEndDragP, cirrInvEnd);
			
		} catch ( Exception ex ) {
			ex.printStackTrace();
		}

		currTrans = (AffineTransform)trans.clone();
		//currTrans.concatenate(signatureTrans);
		// currTrans.translate(diffX, diffY);
		
		// now get the difference of where the center is
		// now figure out just the Y difference between the 2 points
		diffY = cirrInvEnd.getY() - currInvStart.getY();
		diffX = cirrInvEnd.getX() - currInvStart.getX();	
		currTrans.translate(diffX, diffY);
		
		originalRec = el.getRectangle();
		selEl.selectedRectangle = currTrans.createTransformedShape(originalRec);
		selEl.currTrans = currTrans;
		
//		Rectangle2D rec2update = selEl.selectedRectangle.getBounds2D();
//		updateSelectedAreaForRepaint(rec2update);		
//		
		DirtyAreaManager.addDirtyArea(selEl.selectedRectangle);
		
	}

    pixMoved = Math.sqrt(Math.pow(diffX,2) + Math.pow(diffY,2));
    return;
  }

}